home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
xscheme.arc
/
xsdmem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-29
|
15KB
|
680 lines
/* xsdmem.c - xscheme dynamic memory management routines */
/* Copyright (c) 1988, by David Michael Betz
All Rights Reserved
Permission is granted for unrestricted non-commercial use */
#include "xscheme.h"
/* virtual machine registers */
LVAL xlfun; /* current function */
LVAL xlenv; /* current environment */
LVAL xlval; /* value of most recent instruction */
LVAL *xlsp; /* value stack pointer */
/* stack limits */
LVAL *xlstkbase; /* base of value stack */
LVAL *xlstktop; /* top of value stack (actually, one beyond) */
/* variables shared with xsimage.c */
FIXTYPE total; /* total number of bytes of memory in use */
FIXTYPE gccalls; /* number of calls to the garbage collector */
/* node space */
NSEGMENT *nsegments; /* list of node segments */
NSEGMENT *nslast; /* last node segment */
int nscount; /* number of node segments */
FIXTYPE nnodes; /* total number of nodes */
FIXTYPE nfree; /* number of nodes in free list */
LVAL fnodes; /* list of free nodes */
/* vector (and string) space */
VSEGMENT *vsegments; /* list of vector segments */
VSEGMENT *vscurrent; /* current vector segment */
int vscount; /* number of vector segments */
LVAL *vfree; /* next free location in vector space */
LVAL *vtop; /* top of vector space */
/* external variables */
extern LVAL s_unbound; /* *UNBOUND* symbol */
extern LVAL obarray; /* *OBARRAY* symbol */
extern LVAL default_object; /* default object */
extern LVAL eof_object; /* eof object */
extern LVAL true; /* truth value */
/* external routines */
extern unsigned char *calloc();
/* forward declarations */
FORWARD LVAL allocnode();
FORWARD LVAL allocvector();
/* cons - construct a new cons node */
LVAL cons(x,y)
LVAL x,y;
{
LVAL nnode;
/* get a free node */
if ((nnode = fnodes) == NIL) {
check(2);
push(x);
push(y);
findmemory();
if ((nnode = fnodes) == NIL)
xlabort("insufficient node space");
drop(2);
}
/* unlink the node from the free list */
fnodes = cdr(nnode);
--nfree;
/* initialize the new node */
nnode->n_type = CONS;
rplaca(nnode,x);
rplacd(nnode,y);
/* return the new node */
return (nnode);
}
/* newframe - create a new environment frame */
LVAL newframe(parent,size)
LVAL parent; int size;
{
LVAL newframe;
newframe = cons(newvector(size),parent);
newframe->n_type = ENV;
return (newframe);
}
/* cvstring - convert a string to a string node */
LVAL cvstring(str)
unsigned char *str;
{
LVAL val;
val = newstring(strlen(str)+1);
strcpy(getstring(val),str);
return (val);
}
/* cvsymbol - convert a string to a symbol */
LVAL cvsymbol(pname)
unsigned char *pname;
{
LVAL val;
val = allocvector(SYMBOL,SYMSIZE);
cpush(val);
setvalue(val,s_unbound);
setpname(val,cvstring(pname));
setplist(val,NIL);
return (pop());
}
/* cvfixnum - convert an integer to a fixnum node */
LVAL cvfixnum(n)
FIXTYPE n;
{
LVAL val;
if (n >= SFIXMIN && n <= SFIXMAX)
return (cvsfixnum(n));
val = allocnode(FIXNUM);
val->n_int = n;
return (val);
}
/* cvflonum - convert a floating point number to a flonum node */
LVAL cvflonum(n)
FLOTYPE n;
{
LVAL val;
val = allocnode(FLONUM);
val->n_flonum = n;
return (val);
}
/* cvchar - convert an integer to a character node */
LVAL cvchar(ch)
int ch;
{
LVAL val;
val = allocnode(CHAR);
val->n_chcode = ch;
return (val);
}
/* cvclosure - convert code and an environment to a closure */
LVAL cvclosure(code,env)
LVAL code,env;
{
LVAL val;
val = cons(code,env);
val->n_type = CLOSURE;
return (val);
}
/* cvpromise - convert a procedure to a promise */
LVAL cvpromise(code,env)
LVAL code,env;
{
LVAL val;
val = cons(cvclosure(code,env),NIL);
val->n_type = PROMISE;
return (val);
}
/* cvmethod - convert code and an environment to a method */
LVAL cvmethod(code,class)
LVAL code,class;
{
LVAL val;
val = cons(code,class);
val->n_type = METHOD;
return (val);
}
/* cvsubr - convert a function to a subr/xsubr */
LVAL cvsubr(type,fcn,offset)
int type; LVAL (*fcn)(); int offset;
{
LVAL val;
val = allocnode(type);
val->n_subr = fcn;
val->n_offset = offset;
return (val);
}
/* cvport - convert a file pointer to an port */
LVAL cvport(fp,flags)
FILE *fp; int flags;
{
LVAL val;
val = allocnode(PORT);
setfile(val,fp);
setsavech(val,'\0');
setpflags(val,flags);
return (val);
}
/* newvector - allocate and initialize a new vector */
LVAL newvector(size)
int size;
{
return (allocvector(VECTOR,size));
}
/* newstring - allocate and initialize a new string */
LVAL newstring(size)
int size;
{
LVAL val;
val = allocvector(STRING,btow_size(size));
val->n_vsize = size;
return (val);
}
/* newcode - create a new code object */
LVAL newcode(nlits)
int nlits;
{
return (allocvector(CODE,nlits));
}
/* newcontinuation - create a new continuation object */
LVAL newcontinuation(size)
int size;
{
return (allocvector(CONTINUATION,size));
}
/* newobject - allocate and initialize a new object */
LVAL newobject(cls,size)
LVAL cls; int size;
{
LVAL val;
val = allocvector(OBJECT,size+1); /* class, ivars */
setclass(val,cls);
return (val);
}
/* allocnode - allocate a new node */
LOCAL LVAL allocnode(type)
int type;
{
LVAL nnode;
/* get a free node */
if ((nnode = fnodes) == NIL) {
findmemory();
if ((nnode = fnodes) == NIL)
xlabort("insufficient node space");
}
/* unlink the node from the free list */
fnodes = cdr(nnode);
--nfree;
/* initialize the new node */
nnode->n_type = type;
rplacd(nnode,NIL);
/* return the new node */
return (nnode);
}
/* findmemory - garbage collect, then add more node space if necessary */
LOCAL findmemory()
{
NSEGMENT *newnsegment(),*newseg;
LVAL p;
int n;
/* first try garbage collecting */
gc();
/* expand memory only if less than one segment is free */
if (nfree >= (long)NSSIZE)
return;
/* allocate the new segment */
if ((newseg = newnsegment(NSSIZE)) == NULL)
return;
/* add each new node to the free list */
p = &newseg->ns_data[0];
for (n = NSSIZE; --n >= 0; ++p) {
p->n_type = FREE;
p->n_flags = 0;
rplacd(p,fnodes);
fnodes = p;
}
}
/* allocvector - allocate and initialize a new vector node */
LOCAL LVAL allocvector(type,size)
int type,size;
{
register LVAL val,*p;
register int i;
/* get a free node */
if ((val = fnodes) == NIL) {
findmemory();
if ((val = fnodes) == NIL)
xlabort("insufficient node space");
}
/* unlink the node from the free list */
fnodes = cdr(fnodes);
--nfree;
/* initialize the vector node */
val->n_type = type;
val->n_vsize = size;
val->n_vdata = NULL;
cpush(val);
/* add space for the backpointer */
++size;
/* make sure there's enough space */
if (vfree + size >= vtop) {
findvmemory(size);
if (vfree + size >= vtop)
xlabort("insufficient vector space");
}
/* allocate the next available block */
p = vfree;
vfree += size;
/* store the backpointer */
*p++ = top();
val->n_vdata = p;
/* set all the elements to NIL */
for (i = size; i > 1; --i)
*p++ = NIL;
/* return the new vector */
return (pop());
}
/* findvmemory - find vector memory (used by 'xsimage.c') */
findvmemory(size)
int size;
{
VSEGMENT *newvsegment(),*vseg;
/* first try garbage collecting */
gc();
/* look for a vector segment with enough space */
for (vseg = vsegments; vseg != NULL; vseg = vseg->vs_next)
if (vseg->vs_free + size < vseg->vs_top) {
if (vscurrent != NULL)
vscurrent->vs_free = vfree;
vfree = vseg->vs_free;
vtop = vseg->vs_top;
vscurrent = vseg;
return;
}
/* allocate a new vector segment and make it current */
if (vseg = newvsegment(VSSIZE)) {
if (vscurrent != NULL)
vscurrent->vs_free = vfree;
vfree = vseg->vs_free;
vtop = vseg->vs_top;
vscurrent = vseg;
}
}
/* newnsegment - create a new node segment */
NSE